package com.small.proxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;

import net.sf.cglib.proxy.MethodProxy;

/**
 * 代理切面链
 * @author 乐乐
 *
 */
public class ProxyChain {
  @SuppressWarnings("unused")
  private static final Logger logger = Logger.getLogger(ProxyChain.class);
  
  /**
   * 方法返回值
   */
  private static Object methodResult;
  
  /**
   * 过滤链索引  判断循环次数  如果是最后一次循环执行目标方法
   */
  private AtomicInteger index = new AtomicInteger(-1);
  
  /**
   * 目标类
   */
  private Class<?> targetClass;  
  
  /**
   * 目标代理对象
   */
  private Object targetObject;   
  
  /**
   * 目标方法
   */
  private Method targetMethod;   
  
  /**
   * 目标方法参数
   */
  private Object[] methodParams; 
  
  /**
   * 方法代理
   */
  private MethodProxy methodProxy;  
  
  /**
   * 目标拦截器列表
   */
  private List<Proxy> proxies = new ArrayList<Proxy>();  
  
  /** 初始化过滤器链
   * @param targetClass 
   * @param targetObject
   * @param methodParams
   * @param targetMethod
   * @param methodProxy
   * @param proxies
   */
  public ProxyChain(Class<?> targetClass, Object targetObject, Object[] methodParams, Method targetMethod, MethodProxy methodProxy, List<Proxy> proxies) {
    this.proxies = proxies;
    this.methodParams = methodParams;
    this.methodProxy = methodProxy;
    this.targetClass = targetClass;
    this.targetMethod = targetMethod;
    this.targetObject = targetObject;
  }
  
  public Object getMethodResult() {
    return methodResult;
  }
  
  public MethodProxy getMethodProxy() {
    return methodProxy;
  }
  
  public Class<?> getTargetClass() {
    return targetClass;
  }
  
  public Method getTargetMethod() {
    return targetMethod;
  }
  
  public Object[] getMethodParams() {
    return methodParams;
  }
  
  
  /**执行切面链
   * @return
   */
  public Object doChain(){
    
    try {
      
      if (index.intValue() < proxies.size()-1) {
        index.incrementAndGet();
        proxies.get(index.intValue()).doProxy(this);
      }else {
        methodResult = methodProxy.invokeSuper(targetObject, methodParams);
      }
      
    } catch (Throwable e) {
      System.out.println(e.toString());
    }
    return methodResult;
  }
  
}
